package cn.js.sangu.unitStore.common.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.js.sangu.unitStore.common.MyAuthAccess;
import cn.js.sangu.unitStore.common.exception.ServiceException;
import cn.js.sangu.unitStore.entity.User;
import cn.js.sangu.unitStore.mapper.UserMapper;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 说明：JWT拦截器
 * 作者：linshuo
 * 日期：2024/8/8 15:36
 */
public class JwtInterceptor implements HandlerInterceptor {

    @Resource
    private UserMapper userMapper;

    public static final String TOKEN = "token";
    public static final String CODE = "401"; //权限异常
    public static final String MSG = "请登录后再试";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler){
        //放行自定义注解修饰的接口
        if (handler instanceof HandlerMethod){
            //通过框架的handler参数(也就是当作接口的那个方法)，找自定义的注解class文件，获取自定义注解对象实例，来确定这个方法是否有自定义的这个注解
            MyAuthAccess myAuthAccess = ((HandlerMethod) handler).getMethodAnnotation(MyAuthAccess.class);
            if (null != myAuthAccess) return true;  //自定义注解存在，就放行
        }
        //被拦截的请求，开始验证
        String token = request.getHeader(TOKEN);//请求头
        if (StrUtil.isBlank(token)){
            token = request.getParameter(TOKEN); //url参数
        }

        //执行验证
        if (StrUtil.isBlank(token)){
            throw new ServiceException(CODE,MSG); //都没有
        }
        //获取token中的用户信息
        String userId;
        try {
            //把token decode解码，去小仓库拿第一个用户信息Id
            userId = JWT.decode(token).getAudience().get(0); //Audience存信息的小仓库
        } catch (JWTDecodeException e) {
            throw new ServiceException(CODE,MSG);
        }
        //根据token中的userid查询数据库
//        User user = userMapper.findById(Integer.parseInt(userId));
        User user = userMapper.selectById(Integer.parseInt(userId));
        if (null == user){
            throw new ServiceException(CODE,MSG); //查无此人
        }
        //用户密码加签验证token，密码加密之后生成 Verifier验证器
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try {
            DecodedJWT verify = jwtVerifier.verify(token); //验证器对象可直接验证token，错误抛出下方异常
        } catch (JWTVerificationException e) {
            throw new ServiceException(CODE,MSG); //验证token时发生异常，如不匹配
        }
        return true;
    }
}
